/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package hadss.adaptive_video

import android.app.Activity
import android.content.Context
import android.content.pm.ActivityInfo
import android.hardware.Sensor
import android.hardware.SensorManager
import io.flutter.Log
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.EventChannel
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result

private const val TAG = "AdaptiveVideoPlugin"
private const val HADSS_ADAPTIVE_VIDEO = "hadss_adaptive_video"
private const val GRAVITY_ORIENTATION_CHANNEL_NAME = "${HADSS_ADAPTIVE_VIDEO}/gravity_orientation"
private const val SCREEN_ORIENTATION_CHANNEL_NAME = "${HADSS_ADAPTIVE_VIDEO}/screen_orientation"

/** AdaptiveVideoPlugin */
class AdaptiveVideoPlugin : FlutterPlugin, ActivityAware, MethodCallHandler {
    private var activity: Activity? = null
    private var flutterPluginBinding: FlutterPlugin.FlutterPluginBinding? = null
    private var methodChannel: MethodChannel? = null
    private var gravityOrientationChannel: EventChannel? = null
    private var screenOrientationChannel: EventChannel? = null

    private var gravityOrientationStreamHandler: GravityOrientationStreamHandler? = null
    private var screenOrientationStreamHandler: ScreenOrientationStreamHandler? = null

    private var sensorManager: SensorManager? = null
    private var lastGravityOrientation: Int = -1

    fun getUniqueClassName(): String {
        Log.i(TAG, "getUniqueClassName: $TAG")
        return TAG;
    }

    override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        Log.i(TAG, "onAttachedToEngine");
        flutterPluginBinding = binding
        sensorManager =
            flutterPluginBinding!!.applicationContext.getSystemService(Context.SENSOR_SERVICE) as SensorManager
        methodChannel = MethodChannel(flutterPluginBinding!!.binaryMessenger, HADSS_ADAPTIVE_VIDEO)
        methodChannel!!.setMethodCallHandler(this)
        gravityOrientationChannel =
            EventChannel(flutterPluginBinding!!.binaryMessenger, GRAVITY_ORIENTATION_CHANNEL_NAME)
        gravityOrientationStreamHandler = GravityOrientationStreamHandler(sensorManager!!)
        gravityOrientationChannel!!.setStreamHandler(gravityOrientationStreamHandler!!)
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        Log.i(TAG, "onAttachedToActivity");
        activity = binding.activity
        screenOrientationChannel =
            EventChannel(flutterPluginBinding!!.binaryMessenger, SCREEN_ORIENTATION_CHANNEL_NAME)
        screenOrientationStreamHandler = ScreenOrientationStreamHandler(activity!!, sensorManager!!)
        screenOrientationChannel!!.setStreamHandler(screenOrientationStreamHandler!!)
    }

    override fun onDetachedFromActivityForConfigChanges() {
    }

    override fun onDetachedFromActivity() {
        activity = null
        screenOrientationChannel!!.setStreamHandler(null)
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        flutterPluginBinding = null
        methodChannel?.setMethodCallHandler(null)
        gravityOrientationStreamHandler!!.removeOrientationChangedListener();
        gravityOrientationChannel!!.setStreamHandler(null);
    }

    override fun onMethodCall(call: MethodCall, result: Result) {
        when (call.method) {
            "isSensorAvailable" -> result.success(sensorManager!!.getDefaultSensor(Sensor.TYPE_GRAVITY) != null)

            "setGravityUpdateInterval" -> {
                gravityOrientationStreamHandler!!.setUpdateInterval(call.argument<Int>("interval")!!)
                screenOrientationStreamHandler!!.setUpdateInterval(call.argument<Int>("interval")!!)
            }

            "setPortraitUp" -> setOrientation(result, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)

            "setPortraitUser" -> setPortraitUpThenFollowSensor(
                result, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
            )

            "setLandscapeLeftUser" -> setLandscapeThenFollowSensor(
                result, ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
            )

            "setLandscapeRightUser" -> setLandscapeThenFollowSensor(
                result, ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
            )

            "setAutoOrientationUser" -> setOrientation(
                result, ActivityInfo.SCREEN_ORIENTATION_USER
            )

            else -> result.notImplemented()
        }
    }

    /**
     * 设置正常旋转
     */
    private fun setOrientation(result: Result, orientation: Int) {
        gravityOrientationStreamHandler!!.removeOrientationChangedListener()
        activity?.requestedOrientation = orientation
        result.success(true)
    }

    /**
     * 设置竖屏，然后跟随传感器
     */
    private fun setPortraitUpThenFollowSensor(result: Result, orientation: Int) {
        gravityOrientationStreamHandler!!.addOrientationChangedListener(object : (Int) -> Unit {
            override fun invoke(newOrientation: Int) {
                if (lastGravityOrientation == newOrientation) {
                    return
                }
                lastGravityOrientation = newOrientation
                activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
            }
        })
        activity?.requestedOrientation = orientation
        result.success(true)
    }

    /**
     * 设置横屏，然后跟随传感器
     */
    private fun setLandscapeThenFollowSensor(result: Result, orientation: Int) {
        activity?.requestedOrientation = orientation
        gravityOrientationStreamHandler!!.addOrientationChangedListener(object : (Int) -> Unit {
            override fun invoke(newOrientation: Int) {
                if (lastGravityOrientation == newOrientation) {
                    return
                }
                lastGravityOrientation = newOrientation
                activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
            }
        })
        result.success(true)
    }
}
